package com.wolfword.crawler.client.deal;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wolfword.common.domain.Constant;
import com.wolfword.common.enums.ClientStatusEnum;
import com.wolfword.common.util.object.JSONSerielizer;
import com.wolfword.common.util.object.StringUtil;
import com.wolfword.crawler.client.config.Config;
import com.wolfword.crawler.client.dto.CrawlTaskWithHtmlDto;
import com.wolfword.crawler.client.entity.AnalyzedInfoListEntity;
import com.wolfword.crawler.client.entity.CrawlTaskEntity;
import com.wolfword.crawler.client.listener.ApplicationReady;
import com.wolfword.crawler.client.utils.HttpClientUtil;
import com.wolfword.crawler.client.utils.SpringContextUtil;
/**
 * 获取未爬取的根域名
 * @author renwei
 *
 */

public class ConnectServer {
	
	private static final Logger logger = LoggerFactory.getLogger(ConnectServer.class);
	
	private static String hostAddress = ApplicationReady.hostAddress;//主机地址
	private static String hostName = ApplicationReady.hostName;//主机名称
	private static Integer hostPort = ApplicationReady.hostPort;//主机端口
	private static Integer status = ClientStatusEnum.WAITING.getStatus();//状态
	
	
	private static Config con = SpringContextUtil.getBean(Config.class);
	private static String server_host = Config.serverHost!=null ? Config.serverHost : con.getCralwer_server_host();
	private static Integer requestTaskCount = con.getRequestTaskCount();//一次请求的任务数
	private static String htmlTempPath = con.getHtmlTempPath();//文件暂存路径，以json形式
	
	/**
	 * 请求未完成任务
	 * @return
	 * @author ServerZhang
	 * @date 2018年1月12日
	 */
	public static JSONArray getUncrawled(){
		
//		server_host=con.getCralwer_server_host();
//		requestTaskCount=con.getRequestTaskCount();
		String strURL = server_host+"task/listUncrawled";
		logger.info(strURL);

		HttpClientUtil instance = HttpClientUtil.getInstance();
		Map<String, String> map = new HashMap<String, String>();
		map.put("clientName", hostName);
		map.put("clientIp", hostAddress);
		map.put("clientPort", hostPort+"");
		map.put("requestCount", requestTaskCount+"");
		String sendHttpPost = instance.sendHttpPost(strURL, map);
		JSONObject json=null;
		
		if(sendHttpPost!=null){
			json = new JSONObject(sendHttpPost);
		}
		if (json == null) {
			return null;
		}
		if(!Constant.SUCCESS_CODE.equals(json.get("code"))){
			logger.info("500，server has a fata error!");
			return null;
		}
		if(json.get("data")==null||StringUtil.isEmpty(String.valueOf(json.get("data")))){
			return null;
		}
		Object dataObj = json.get("data");
		if (dataObj == null) {
			return null;
		}
		logger.info(dataObj.toString());
		String jsonStr = dataObj.toString();//检查字符串是否合法
		if (!jsonStr.startsWith("[") || !jsonStr.endsWith("]")) {
			logger.error("返回的数据格式有误！");
			return null;
		}
		JSONArray jsonArray = new JSONArray(jsonStr);
		int length = jsonArray.length();
		if (length > 0) {
			status = ClientStatusEnum.WORKING.getStatus();
		}else {
			status = ClientStatusEnum.WAITING.getStatus();
		}
		return jsonArray;
	}
	/**
	 * 插入新任务
	 * @param taskEntity
	 * @author ServerZhang
	 * @date 2018年1月12日
	 */
	public static void insertNewTask(List<CrawlTaskEntity> taskEntitys){
		String strURL = server_host+"task/insertTask";
		String taskJson = JSONSerielizer.toJson(taskEntitys, null, null);
		if (StringUtil.isEmpty(taskJson)) {
			return;
		}
		HttpClientUtil instance = HttpClientUtil.getInstance();
		Map<String, String> map = new HashMap<String, String>();
		map.put("taskJson", taskJson);
		instance.sendHttpPost(strURL, map);
	}
	/**
	 * 上传子页面
	 * @param subpages
	 * @author ServerZhang
	 * @date 2018年1月18日
	 */
	public static void uploadSubpage(List<CrawlTaskEntity> subpages){
		String strURL = server_host+"task/uploadSubpage";
		String taskJson = JSONSerielizer.toJson(subpages, null, null);
		if (StringUtil.isEmpty(taskJson)) {
			return;
		}
		HttpClientUtil instance = HttpClientUtil.getInstance();
		Map<String, String> map = new HashMap<String, String>();
		map.put("taskJson", taskJson);
		instance.sendHttpPost(strURL, map);
	}
	/**
	 * 上传子页面（以文件形式）
	 * @param subpages
	 * @author ServerZhang
	 * @date 2018年1月18日
	 */
	public static void uploadSubpageFile(List<CrawlTaskWithHtmlDto> subpages){
		String strURL = server_host+"task/uploadSubpage";
		String jsonStr = JSONSerielizer.toJson(subpages, null, null);
		if (StringUtil.isEmpty(jsonStr)) {
			return;
		}
		//1.写入到本地文件
		String uuid = StringUtil.getUUID();
		//将json以文件的形式保存在暂存目录
		if (StringUtil.isEmpty(htmlTempPath)) {
			htmlTempPath = "./temp/";
		}
		File pFile = new File(htmlTempPath);
		if (!pFile.exists()) {
			pFile.mkdirs();
		}
		String path = StringUtil.connectAsFilePath(htmlTempPath,uuid+".json");
		File jsonFile = new File(path);
		
		FileOutputStream fos = null;
		Writer writer = null;
		try {
			fos = new FileOutputStream(jsonFile);
			writer = new OutputStreamWriter(fos, "UTF-8");
			writer.write(jsonStr);
			writer.flush();
			writer.close();
			fos.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				if (writer != null) {
					writer.close();
				}
				if (fos != null) {
					fos.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		//2.上传到服务器
		jsonFile = new File(path);
		if (!jsonFile.exists()) {
			return;
		}
		DataInputStream in = null;
		OutputStream out = null;
		HttpURLConnection conn = null;
		InputStream ins = null;
		ByteArrayOutputStream outStream = null; 
		try {
			URL url = new URL(server_host+"task/uploadSubpageFile");
			conn = (HttpURLConnection) url.openConnection();
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Content-Type", "text/html");
			conn.setRequestProperty("Cache-Control", "no-cache");
			conn.setRequestProperty("Charsert", "UTF-8");
			conn.connect();
			conn.setConnectTimeout(10000);
			out = conn.getOutputStream();

			in = new DataInputStream(new FileInputStream(jsonFile));
			int bytes = 0;
			byte[] buffer = new byte[1024];
			while ((bytes = in.read(buffer)) != -1) {
				out.write(buffer, 0, bytes);
			}
			out.flush();

			// 返回流
			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
				ins = conn.getInputStream();
				outStream = new ByteArrayOutputStream();
				byte[] data = new byte[1024];
				int count = -1;
				while ((count = ins.read(data, 0, 1024)) != -1) {
					outStream.write(data, 0, count);
				}
				data = null;
			}
		} catch (Exception e) {
			logger.error("上传json文件到服务器失败！");
			return;
		}finally{
			try {
				if (in != null) {
					in.close();
				}
				if (out != null) {
					out.close();
				}
				if (ins != null) {
					ins.close();
				}
				if (outStream != null) {
					outStream.close();
				}
				if (conn != null) {
					conn.disconnect();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		//3.删除该文件
		jsonFile.delete();
		
	}
	/**
	 * 反馈爬取结果
	 * @param taskEntity
	 * @author ServerZhang
	 * @date 2018年1月12日
	 */
	public static void updateTask(List<CrawlTaskWithHtmlDto> taskEntitys){
		String strURL = server_host+"task/updateTask";
		String taskJson = JSONSerielizer.toJson(taskEntitys, null, null);
		if (StringUtil.isEmpty(taskJson)) {
			return;
		}
		HttpClientUtil instance = HttpClientUtil.getInstance();
		Map<String, String> map = new HashMap<String, String>();
		map.put("taskJson", taskJson);
		instance.sendHttpPost(strURL, map);
	}
	/**
	 * 反馈爬取结果
	 * @param taskEntity
	 * @author ServerZhang
	 * @date 2018年1月12日
	 */
	public static void updateTaskFile(List<CrawlTaskWithHtmlDto> taskEntities){
		String jsonStr = JSONSerielizer.toJson(taskEntities, null, null);
		if (StringUtil.isEmpty(jsonStr)) {
			return;
		}
		//1.写入到本地文件
		String uuid = StringUtil.getUUID();
		//将json以文件的形式保存在暂存目录
		if (StringUtil.isEmpty(htmlTempPath)) {
			htmlTempPath = "./temp/";
		}
		File pFile = new File(htmlTempPath);
		if (!pFile.exists()) {
			pFile.mkdirs();
		}
		String path = StringUtil.connectAsFilePath(htmlTempPath,uuid+".json");
		File jsonFile = new File(path);
		
		FileOutputStream fos = null;
		Writer writer = null;
		try {
			fos = new FileOutputStream(jsonFile);
			writer = new OutputStreamWriter(fos, "UTF-8");
			writer.write(jsonStr);
			writer.flush();
			writer.close();
			fos.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				if (writer != null) {
					writer.close();
				}
				if (fos != null) {
					fos.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		//2.上传到服务器
		jsonFile = new File(path);
		if (!jsonFile.exists()) {
			return;
		}
		DataInputStream in = null;
		OutputStream out = null;
		HttpURLConnection conn = null;
		InputStream ins = null;
		ByteArrayOutputStream outStream = null; 
		try {
			URL url = new URL(server_host+"task/updateTaskFile");
			conn = (HttpURLConnection) url.openConnection();
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Content-Type", "text/html");
			conn.setRequestProperty("Cache-Control", "no-cache");
			conn.setRequestProperty("Charsert", "UTF-8");
			conn.connect();
			conn.setConnectTimeout(10000);
			out = conn.getOutputStream();

			in = new DataInputStream(new FileInputStream(jsonFile));
			int bytes = 0;
			byte[] buffer = new byte[1024];
			while ((bytes = in.read(buffer)) != -1) {
				out.write(buffer, 0, bytes);
			}
			out.flush();

			// 返回流
			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
				ins = conn.getInputStream();
				outStream = new ByteArrayOutputStream();
				byte[] data = new byte[1024];
				int count = -1;
				while ((count = ins.read(data, 0, 1024)) != -1) {
					outStream.write(data, 0, count);
				}
				data = null;
			}
		} catch (Exception e) {
			logger.error("上传json文件到服务器失败！");
			return;
		}finally{
			try {
				if (in != null) {
					in.close();
				}
				if (out != null) {
					out.close();
				}
				if (ins != null) {
					ins.close();
				}
				if (outStream != null) {
					outStream.close();
				}
				if (conn != null) {
					conn.disconnect();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		//3.删除该文件
		jsonFile.delete();
	}
	/**
	 * 发送自己的状态
	 * @param taskEntity
	 * @author ServerZhang
	 * @date 2018年1月12日
	 */
	public static void sendMyStatus(){
		if (StringUtil.isEmpty(hostAddress,hostPort,status)) {
			return;
		}
		String strURL = server_host+"client/log/addClientStatus";
		HttpClientUtil instance = HttpClientUtil.getInstance();
		Map<String, String> map = new HashMap<String, String>();
		map.put("clientIp", hostAddress);
		map.put("clientPort", hostPort+"");
		map.put("clientStatus", status+"");
		instance.sendHttpPost(strURL, map);
	}
	/**
	 * 批量插入网页解析内容
	 * @param infoListEntities
	 * @author ServerZhang
	 * @date 2018年1月16日
	 */
	public static void insertAnalysisInfo(List<AnalyzedInfoListEntity> infoListEntities){
		String strURL = server_host+"analysis/info/batchInsert";
		String infoJson = JSONSerielizer.toJson(infoListEntities, null, null);
		if (StringUtil.isEmpty(infoJson)) {
			return;
		}
		HttpClientUtil instance = HttpClientUtil.getInstance();
		Map<String, String> map = new HashMap<String, String>();
		map.put("infoJson", infoJson);
		instance.sendHttpPost(strURL, map);
	}
	/**
	 * 请求中心服务器获取根域名
	 * @return
	 */
	public static JSONObject getRootUrl(){
//		String hostAddress = ApplicationReady.hostAddress;
//		Integer hostPort = ApplicationReady.hostPort;
		
//		server_host=con.getCralwer_server_host();
		String strURL = server_host+"rootUrl";
		logger.info(strURL);
		URL url;
		BufferedReader reader = null;
		JSONObject json=null;
		HttpURLConnection httpConn = null;
		try {
			url = new URL(strURL);
			httpConn = (HttpURLConnection) url
					.openConnection();
			httpConn.setRequestMethod("POST");
			httpConn.setDoOutput(false);
			httpConn.connect();
			
			reader = new BufferedReader(new InputStreamReader(
					httpConn.getInputStream()));
			
			String line;
			StringBuffer buffer = new StringBuffer();
			while ((line = reader.readLine()) != null) {
				buffer.append(line);
			}
			
			reader.close();
			httpConn.disconnect();
			if(buffer!=null)
				json = new JSONObject(buffer.toString());
			if(json!=null){
				if(Constant.SUCCESS_CODE.equals(json.get("code"))){
					if(json.get("data")==null||StringUtil.isEmpty(String.valueOf(json.get("data")))){
						return null;
					}else{
						logger.info(json.get("data")+"");
						json= (JSONObject) json.get("data");
					}
					
				}else{
					logger.info("500，server has a fata error!");
					return null;
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			if (httpConn != null) {
				httpConn.disconnect();
			}
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return json;
	}
	/**
	 * 向中心服务器上传文件
	 * @param store_path
	 * @param contain_str
	 * @throws IOException
	 */
	public static void uploadFiles(String store_path,String contain_str)throws IOException{
//		server_host=con.getCralwer_server_host();
		DataInputStream in = null;
		OutputStream out = null;
		HttpURLConnection conn = null;
		InputStream ins = null;
		ByteArrayOutputStream outStream = null; 
		try {
			File file = new File(store_path);
			File[] f = file.listFiles();
			for (int i = 0; i < f.length; i++) {
				if (f[i].isFile()) {
					String name = f[i].getName();
					URL url = new URL(
							server_host+"api/upload-files?name="
									+ name+"&contain_str="+contain_str);
					conn = (HttpURLConnection) url.openConnection();
					// 发送POST请求必须设置如下两行
					conn.setDoOutput(true);
					conn.setUseCaches(false);
					conn.setRequestMethod("POST");
					conn.setRequestProperty("Content-Type", "text/html");
					conn.setRequestProperty("Cache-Control", "no-cache");
					conn.setRequestProperty("Charsert", "UTF-8");
					conn.connect();
					conn.setConnectTimeout(10000);
					out = conn.getOutputStream();

					// File file = new File("F:/htmls/zhihu/B/A");

					in = new DataInputStream(new FileInputStream(f[i]));
					int bytes = 0;
					byte[] buffer = new byte[1024];
					while ((bytes = in.read(buffer)) != -1) {
						out.write(buffer, 0, bytes);
					}
					out.flush();

					// 返回流
					if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
						ins = conn.getInputStream();
						outStream = new ByteArrayOutputStream();
						byte[] data = new byte[1024];
						int count = -1;
						while ((count = ins.read(data, 0, 1024)) != -1) {
							outStream.write(data, 0, count);
						}
						data = null;
					}
				}else{
					uploadFiles(f[i].getPath(),contain_str);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (in != null) {
				in.close();
			}
			if (out != null) {
				out.close();
			}
			if (ins != null) {
				ins.close();
			}
			if (outStream != null) {
				outStream.close();
			}
			if (conn != null) {
				conn.disconnect();
			}
		}
	}
	
	
	/**
	 * 爬取完成调用服务端统计接口
	 * @return
	 */
	public static void statistics(String root_url){
//		server_host=con.getCralwer_server_host();
		String strURL = server_host+"api/statistics";
		logger.info(strURL);
		URL url;
		BufferedReader reader;
		JSONObject json=null;
		try {
			url = new URL(strURL+"?url="+root_url);
			HttpURLConnection httpConn = (HttpURLConnection) url
					.openConnection();
			httpConn.setRequestMethod("POST");
			httpConn.connect();

			reader = new BufferedReader(new InputStreamReader(
					httpConn.getInputStream()));
			String line;
			StringBuffer buffer = new StringBuffer();
			while ((line = reader.readLine()) != null) {
				buffer.append(line);
			}
			reader.close();
			httpConn.disconnect();
			if(buffer!=null)
				json = new JSONObject(buffer.toString());
			if(json!=null){
				if(Constant.SUCCESS_CODE.equals(json.get("code"))){
					logger.info("----------------------------->统计子网页和parent_url_id成功");
				}else{
					logger.info("500，server has a fata error!");
				}
			}
					
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}
